//
// Created by fazhehy on 2024/6/7.
//

#include "menu.h"

xPage pageBuffer[MAX_PAGE_NUM];
uint8_t pageBufferPointer = 0;

xpPage add_page(char * name, xpPage parentPage, uint8_t(*func)(uint8_t))
{
    if (pageBufferPointer >= MAX_PAGE_NUM)
        return NULL;
    xpPage subPage = pageBuffer+pageBufferPointer;
    pageBufferPointer ++;

    subPage->name = name;
    subPage->parentPage = parentPage;
    subPage->func = func;

    if (parentPage == NULL)
    {
        subPage->lastPage = NULL;
        subPage->nextPage = NULL;
    }
    else
    {
        if (parentPage->subPageHead == NULL)
        {
            subPage->lastPage = NULL;
            parentPage->subPageHead = subPage;
            parentPage->subPageTail = subPage;
            parentPage->selectSubPage = subPage;
//            parentPage->show.showStartPage = subPage;
        }
        else
        {
            subPage->lastPage = parentPage->subPageTail;
            parentPage->subPageTail->nextPage = subPage;
            parentPage->subPageTail = subPage;
        }
    }
    return subPage;
}

xpPage nowPage;
uint8_t menu_move(uint8_t keyNum)
{
    if (nowPage->func != NULL)
        keyNum = nowPage->func(keyNum);

    uint8_t moveDir = NOP;

    if (keyNum == DOWN){
        if (nowPage->selectSubPage->nextPage != NULL){
            nowPage->selectSubPage = nowPage->selectSubPage->nextPage;
            moveDir = DOWN;
        }
    }
    else if (keyNum == UP){
        if (nowPage->selectSubPage->lastPage != NULL){
            nowPage->selectSubPage = nowPage->selectSubPage->lastPage;
            moveDir = UP;
        }
    }
    else if (keyNum == ENTER){
        if (nowPage->selectSubPage->subPageHead != NULL || nowPage->selectSubPage->func != NULL){
            nowPage = nowPage->selectSubPage;
            moveDir = ENTER;
        }

    }
    else if (keyNum == BACK){
        if (nowPage->parentPage != NULL){
            nowPage = nowPage->parentPage;
            nowPage->selectSubPage = nowPage->subPageHead;
            moveDir = BACK;
        }
    }
    else if (keyNum == NO_SHOW){
        moveDir = NO_SHOW;
    }

    return moveDir;
}

struct {
    uint8_t framePos;
    xpPage showStartPage;
}show;
void menu_show(uint8_t moveDir)
{
    if (moveDir != NO_SHOW && moveDir != NOP){
        if (moveDir == DOWN){   //下一项
            uint8_t frameLen = strlen(nowPage->selectSubPage->lastPage->name)*FONT_WIDTH+ROUND_RECT_R;
            st7789_draw_round_rectangle(DISPLAY_OFFSET_X, (show.framePos)*(FONT_HEIGHT+4)+DISPLAY_OFFSET_Y, frameLen, FONT_HEIGHT+4, ROUND_RECT_R, ST7789_BG_COLOR);
            if (show.framePos >= MAX_SHOW_NUM-1){ //如果到了最末尾
                xpPage pPage = show.showStartPage;
                uint8_t i = 0;
                while (pPage != NULL){
                    pPage = pPage->nextPage;
                    i ++;
                }
                if (i >= MAX_SHOW_NUM-1) { //如果大于MAX_SHOW_NUM 则可以更新
                    show.showStartPage = show.showStartPage->nextPage;
                    st7789_clear();
                }
            }
            else{
                show.framePos ++;
            }
        }
        else if (moveDir == UP){//上一项
            uint8_t frameLen = strlen(nowPage->selectSubPage->nextPage->name)*FONT_WIDTH+ROUND_RECT_R;
            st7789_draw_round_rectangle(DISPLAY_OFFSET_X, (show.framePos)*(FONT_HEIGHT+4)+DISPLAY_OFFSET_Y, frameLen, FONT_HEIGHT+4, ROUND_RECT_R, ST7789_BG_COLOR);
            if (show.framePos == 0){ // 如果到了最开始
                if (show.showStartPage->lastPage != NULL) {
                    show.showStartPage = show.showStartPage->lastPage;
                    st7789_clear();
                }
            }
            else{
                show.framePos --;
            }
        }
        else if (moveDir == ENTER || moveDir == BACK){
            st7789_clear();
            show.showStartPage = nowPage->subPageHead;
            if (nowPage->parentPage != NULL)
                show.framePos = 0;
        }
        if (nowPage->selectSubPage != NULL){
            uint8_t frameLen = strlen(nowPage->selectSubPage->name)*FONT_WIDTH+ROUND_RECT_R;
            xpPage showSubPage = show.showStartPage;
            st7789_show_string(40, 2, nowPage->name);
            uint8_t i = 0;
            while (i < MAX_SHOW_NUM){
                st7789_show_string(DISPLAY_OFFSET_X + 2, i * (FONT_HEIGHT + 4) + 2 + DISPLAY_OFFSET_Y,showSubPage->name);
                if (showSubPage->nextPage == NULL)
                    break;
                showSubPage = showSubPage->nextPage;
                i ++;
            }
            st7789_draw_round_rectangle(DISPLAY_OFFSET_X, (show.framePos)*(FONT_HEIGHT+4)+DISPLAY_OFFSET_Y, frameLen, FONT_HEIGHT+4, ROUND_RECT_R, ST7789_PEN_COLOR);
        }
    }
}

void menu_task()
{
    uint8_t keyNum = get_key_num();
    switch (keyNum) {
        case 2: keyNum = UP; break;
        case 1: keyNum = DOWN; break;
        case 3: keyNum = ENTER; break;
        case 4: keyNum = BACK; break;
        default: keyNum = 0; break;
    }
    do{
        protocol_send_command(keyNum, adc_value[2], adc_value[3]);
    } while (remote.state != NORMAL && remote.transmitBufferLen != 0);
    if (remote.protocolState == 1){
        remote.protocolState = 0;
        if (remote.menuOperation != 0)
            keyNum = remote.menuOperation;
        remote.menuOperation = 0;
    }
    menu_show(menu_move(keyNum));
}

void menu_init()
{
    xpPage MainPage = add_page("SUV menu", NULL, NULL);

    xpPage configTaskPage;

    xpPage outdoorTaskPage = add_page("outdoor", MainPage, NULL);
    configTaskPage = add_page("kun run", outdoorTaskPage, outdoor_kun_config);
    add_page("kun run", configTaskPage, outdoor_kun_run);
    configTaskPage = add_page("precise kun", outdoorTaskPage, outdoor_precise_config);
    add_page("precise kun", configTaskPage, outdoor_precise_run);

    xpPage indoorTaskPage = add_page("indoor", MainPage, NULL);
    configTaskPage = add_page("kun run", indoorTaskPage, indoor_kun_config);
    add_page("kun run", configTaskPage, indoor_kun_run);
    configTaskPage = add_page("precise run", indoorTaskPage, indoor_precise_config);
    add_page("precise run", configTaskPage, indoor_precise_run);

    add_page("record point", MainPage, record_point_task);
    add_page("remote control", MainPage, remote_control_task);
    add_page("set mag deviate angle", MainPage, set_mag_deviate_angle);
//    add_page("mag calibration", MainPage, mag_calibration_task);
    add_page("show attitude", MainPage, show_attitude_task);
    add_page("flash write parameter", MainPage, flash_write_param_task);
    add_page("flash write point", MainPage, flash_write_point_task);

    /*---------------------不允许修改----------------------------*/
    nowPage = MainPage;
    show.showStartPage = MainPage->subPageHead;
    menu_show(ONLY_SHOW);
}
